﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace iNet.Media.Imaging.Filters
{
	/// <summary>
	/// 亮度調整濾鏡工作。
	/// </summary>
	public class BrightnessFilterTask : SimpleColorTransformFilterTask
	{
		#region 欄位
		double _Brightness;
		double _BrightPartAdjustment;
		double _DarkPartAdjustment;
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 BrightnessFilterTask 執行個體。
		/// </summary>
		public BrightnessFilterTask()
		{ }
		/// <summary>
		/// 初始化新的 BrightnessFilterTask 執行個體。
		/// </summary>
		/// <param name="sourceBitmap">來源點陣圖。</param>
		/// <param name="brightness">亮度調整值，範圍為 -1 ~ 1。-1 表示最暗；1 表示最亮；0 表示原始亮度。</param>
		/// <exception cref="ArgumentOutOfRangeException">brightness 不是 -1 ~ 1 (包含) 之間的值。</exception>
		public BrightnessFilterTask(IBitmapImage sourceBitmap, double brightness)
			: base(sourceBitmap)
		{
			if (brightness < -1 || brightness > 1)
				throw new ArgumentOutOfRangeException("brightness");
			_Brightness = brightness;
		}
		#endregion
		#region ApplyFilter
		/// <summary>
		/// 套用濾鏡至點陣圖。
		/// </summary>
		/// <param name="version">工作版本。</param>
		/// <param name="filterData">套用濾鏡所需的資料。</param>
		/// <returns>True 表示濾鏡套用成功或取消，False 表示失敗。</returns>
		protected override bool ApplyFilter(Tasks.TaskVersion version, BitmapImageFilterData filterData)
		{
			//取得資料
			double brightness;
			double brightPartAdjustment, darkPartAdjustment;
			if (!this.ReadValue<double>(version, ref _Brightness, out brightness)
				|| !this.ReadValue<double>(version, ref _BrightPartAdjustment, out brightPartAdjustment)
				|| !this.ReadValue<double>(version, ref _DarkPartAdjustment, out darkPartAdjustment))
			{
				return true;
			}

			//建立暗部轉換表
			int colorCount = (filterData.Is16BitsColor ? 65536 : 256);
			int darkPartThreshold = (colorCount / 2);
			int[] table = new int[colorCount];
			if (darkPartAdjustment == 0)
			{
				for (int i = darkPartThreshold; i >= 0; --i)
					table[i] = i;
			}
			else
			{
				darkPartAdjustment /= 2;
				double coeff1 = (1 - darkPartAdjustment);
				double coeff2 = (darkPartThreshold * darkPartAdjustment);
				for (int i = darkPartThreshold; i >= 0; --i)
					table[i] = (int)(coeff1 * i + coeff2);
			}

			//建立亮部轉換表
			if (brightPartAdjustment == 0)
			{
				for (int i = darkPartThreshold + 1; i < colorCount; ++i)
					table[i] = i;
			}
			else
			{
				brightPartAdjustment /= 2;
				double coeff1 = (1 - brightPartAdjustment);
				double coeff2 = (darkPartThreshold * brightPartAdjustment);
				for (int i = darkPartThreshold + 1; i < colorCount; ++i)
					table[i] = (int)(coeff1 * i + coeff2);
			}

			//建立總亮度轉換表
			if (brightness != 0)
			{
				int maxColor = (colorCount - 1);
				int colorShift = (int)(brightness * maxColor);
				for (int i = colorCount - 1; i >= 0; --i)
					table[i] = Math.Max(Math.Min(maxColor, (table[i] + colorShift)), 0);


				table = ColorTransformTableFactory.CreateLinearBrightnessTransform(colorCount, brightness);
			}
			if (this.Channels == BitmapImageFilterChannels.Luminance)
				this.LuminanceTransformTable = table;
			else
			{
				this.AlphaTransformTable = table;
				this.RedColorTransformTable = table;
				this.GreenColorTransformTable = table;
				this.BlueColorTransformTable = table;
			}

			//套用濾鏡
			return base.ApplyFilter(version, filterData);
		}
		#endregion
		#region Brightness
		/// <summary>
		/// 取得或設定亮度調整值，範圍為 -1 ~ 1。-1 表示最暗；1 表示最亮；0 表示原始亮度，預設值為 0。
		/// </summary>
		public double Brightness
		{
			get
			{
				return _Brightness;
			}
			set
			{
				if (value < -1 || value > 1)
					throw new ArgumentOutOfRangeException();
				this.SetInitializingParameter<double>(ref _Brightness, value);
			}
		}
		#endregion
		#region BrightPartAdjustment
		/// <summary>
		/// 取得或設定亮部的拉暗幅度，範圍為 0 ~ 1，預設值為 0。
		/// </summary>
		public double BrightPartAdjustment
		{
			get
			{
				return _BrightPartAdjustment;
			}
			set
			{
				if (value < 0 || value > 1)
					throw new ArgumentOutOfRangeException();
				this.SetInitializingParameter<double>(ref _BrightPartAdjustment, value);
			}
		}
		#endregion
		#region DarkPartAdjustment
		/// <summary>
		/// 取得或設定暗部的拉亮幅度，範圍為 0 ~ 1，預設值為 0。
		/// </summary>
		public double DarkPartAdjustment
		{
			get
			{
				return _DarkPartAdjustment;
			}
			set
			{
				if (value < 0 || value > 1)
					throw new ArgumentOutOfRangeException();
				this.SetInitializingParameter<double>(ref _DarkPartAdjustment, value);
			}
		}
		#endregion
	}
}
